/**
 * SphericalHarmonics.js
 * 
 * 球谐函数(Spherical Harmonics)颜色计算
 * 用于Gaussian Splatting中的视角相关颜色渲染
 */

/**
 * 球谐函数基础计算
 */
export class SphericalHarmonics {
    /**
     * 计算球谐函数基函数值
     * @param {number} l - 阶数
     * @param {number} m - 次数
     * @param {number} theta - 极角 (0 到 π)
     * @param {number} phi - 方位角 (0 到 2π)
     * @returns {number} 球谐函数值
     */
    static evaluate(l, m, theta, phi) {
        // 简化的球谐函数实现，支持到2阶
        const cosTheta = Math.cos(theta);
        const sinTheta = Math.sin(theta);
        
        if (l === 0) {
            // Y_0^0 = 1/(2*sqrt(π))
            return 0.28209479177387814; // 1/(2*sqrt(π))
        } else if (l === 1) {
            if (m === -1) {
                // Y_1^{-1} = sqrt(3/(4π)) * sin(θ) * sin(φ)
                return 0.4886025119029199 * sinTheta * Math.sin(phi);
            } else if (m === 0) {
                // Y_1^0 = sqrt(3/(4π)) * cos(θ)
                return 0.4886025119029199 * cosTheta;
            } else if (m === 1) {
                // Y_1^1 = -sqrt(3/(4π)) * sin(θ) * cos(φ)
                return -0.4886025119029199 * sinTheta * Math.cos(phi);
            }
        } else if (l === 2) {
            if (m === -2) {
                // Y_2^{-2} = sqrt(15/(4π)) * sin²(θ) * sin(2φ)
                return 1.0925484305920792 * sinTheta * sinTheta * Math.sin(2 * phi);
            } else if (m === -1) {
                // Y_2^{-1} = sqrt(15/(4π)) * sin(θ) * cos(θ) * sin(φ)
                return 1.0925484305920792 * sinTheta * cosTheta * Math.sin(phi);
            } else if (m === 0) {
                // Y_2^0 = sqrt(5/(16π)) * (3cos²(θ) - 1)
                return 0.31539156525252005 * (3 * cosTheta * cosTheta - 1);
            } else if (m === 1) {
                // Y_2^1 = -sqrt(15/(4π)) * sin(θ) * cos(θ) * cos(φ)
                return -1.0925484305920792 * sinTheta * cosTheta * Math.cos(phi);
            } else if (m === 2) {
                // Y_2^2 = sqrt(15/(16π)) * sin²(θ) * cos(2φ)
                return 0.5462742152960396 * sinTheta * sinTheta * Math.cos(2 * phi);
            }
        }
        
        return 0;
    }
    
    /**
     * 从视角方向计算球坐标
     * @param {THREE.Vector3} viewDirection - 视角方向向量（已归一化）
     * @returns {Object} {theta, phi} 球坐标
     */
    static cartesianToSpherical(viewDirection) {
        const x = viewDirection.x;
        const y = viewDirection.y;
        const z = viewDirection.z;
        
        // 计算极角 θ (0 到 π)
        const theta = Math.acos(Math.max(-1, Math.min(1, z)));
        
        // 计算方位角 φ (0 到 2π)
        let phi = Math.atan2(y, x);
        if (phi < 0) phi += 2 * Math.PI;
        
        return { theta, phi };
    }
    
    /**
     * 计算球谐函数颜色
     * @param {Array} shCoefficients - 球谐系数数组 [sh0_r, sh0_g, sh0_b, sh1_r, ...]
     * @param {THREE.Vector3} viewDirection - 视角方向
     * @returns {THREE.Vector3} RGB颜色
     */
    static computeColor(shCoefficients, viewDirection) {
        const { theta, phi } = this.cartesianToSpherical(viewDirection);
        
        let r = 0, g = 0, b = 0;
        
        // 球谐函数基函数索引映射
        const shBases = [
            { l: 0, m: 0 },   // SH0
            { l: 1, m: -1 },  // SH1
            { l: 1, m: 0 },   // SH2
            { l: 1, m: 1 },   // SH3
            { l: 2, m: -2 },  // SH4
            { l: 2, m: -1 },  // SH5
            { l: 2, m: 0 },   // SH6
            { l: 2, m: 1 },   // SH7
            { l: 2, m: 2 }    // SH8
        ];
        
        const maxBases = Math.min(shBases.length, shCoefficients.length / 3);
        
        for (let i = 0; i < maxBases; i++) {
            const { l, m } = shBases[i];
            const basis = this.evaluate(l, m, theta, phi);
            
            const coeffIndex = i * 3;
            if (coeffIndex + 2 < shCoefficients.length) {
                r += shCoefficients[coeffIndex] * basis;
                g += shCoefficients[coeffIndex + 1] * basis;
                b += shCoefficients[coeffIndex + 2] * basis;
            }
        }
        
        // 确保颜色值在合理范围内
        r = Math.max(0, Math.min(1, r));
        g = Math.max(0, Math.min(1, g));
        b = Math.max(0, Math.min(1, b));
        
        return { r, g, b };
    }
    
    /**
     * 简化的SH颜色计算（仅使用前4个系数）
     * @param {Array} sh0 - SH0系数 [r, g, b]
     * @param {Array} sh1 - SH1系数 [r, g, b] (可选)
     * @param {Array} sh2 - SH2系数 [r, g, b] (可选)
     * @param {Array} sh3 - SH3系数 [r, g, b] (可选)
     * @param {THREE.Vector3} viewDirection - 视角方向
     * @returns {Object} {r, g, b} 颜色
     */
    static computeSimpleColor(sh0, sh1, sh2, sh3, viewDirection) {
        const { theta, phi } = this.cartesianToSpherical(viewDirection);
        
        // 计算基函数值
        const y0 = this.evaluate(0, 0, theta, phi);   // 常数项
        const y1 = sh1 ? this.evaluate(1, -1, theta, phi) : 0;  // sin(θ)sin(φ)
        const y2 = sh2 ? this.evaluate(1, 0, theta, phi) : 0;   // cos(θ)
        const y3 = sh3 ? this.evaluate(1, 1, theta, phi) : 0;   // sin(θ)cos(φ)
        
        let r = sh0[0] * y0;
        let g = sh0[1] * y0;
        let b = sh0[2] * y0;
        
        if (sh1) {
            r += sh1[0] * y1;
            g += sh1[1] * y1;
            b += sh1[2] * y1;
        }
        
        if (sh2) {
            r += sh2[0] * y2;
            g += sh2[1] * y2;
            b += sh2[2] * y2;
        }
        
        if (sh3) {
            r += sh3[0] * y3;
            g += sh3[1] * y3;
            b += sh3[2] * y3;
        }
        
        // 确保颜色值在合理范围内
        r = Math.max(0, Math.min(1, r));
        g = Math.max(0, Math.min(1, g));
        b = Math.max(0, Math.min(1, b));
        
        return { r, g, b };
    }
}

/**
 * 球谐函数着色器代码生成器
 */
export class SHShaderGenerator {
    /**
     * 生成球谐函数GLSL代码
     * @param {number} maxDegree - 最大阶数 (0, 1, 2)
     * @returns {string} GLSL代码
     */
    static generateSHCode(maxDegree = 2) {
        let code = `
// 球谐函数计算
vec3 computeSHColor(vec3 viewDir, vec3 sh0, vec3 sh1, vec3 sh2, vec3 sh3) {
    // 转换为球坐标
    float theta = acos(clamp(viewDir.z, -1.0, 1.0));
    float phi = atan(viewDir.y, viewDir.x);
    if (phi < 0.0) phi += 2.0 * 3.14159265359;
    
    float cosTheta = cos(theta);
    float sinTheta = sin(theta);
    
    // SH基函数
    float y0 = 0.28209479177387814; // Y_0^0
    
    vec3 color = sh0 * y0;
`;

        if (maxDegree >= 1) {
            code += `
    // 一阶球谐函数
    float y1_neg1 = 0.4886025119029199 * sinTheta * sin(phi);  // Y_1^{-1}
    float y1_0 = 0.4886025119029199 * cosTheta;                // Y_1^0
    float y1_pos1 = -0.4886025119029199 * sinTheta * cos(phi); // Y_1^1
    
    color += sh1 * y1_neg1;
    color += sh2 * y1_0;
    color += sh3 * y1_pos1;
`;
        }

        if (maxDegree >= 2) {
            code += `
    // 二阶球谐函数（如果有更多SH系数）
    // 这里可以扩展更多的SH项
`;
        }

        code += `
    return clamp(color, 0.0, 1.0);
}
`;

        return code;
    }
}